﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.TestManagement.Client;

namespace TFSTools.TFSLibrary
{
    public sealed class TFSGroupSecurity : TFSServerEntity
    {
        private IGroupSecurityService serverGroupSecurityService;

        internal TFSGroupSecurity(ITFSConnection connection)
            : base(connection)
        {
            this.serverGroupSecurityService = SelectedTeamProjectCollection.GetService<IGroupSecurityService>();
        }

        internal IGroupSecurityService Service { get { return this.serverGroupSecurityService; } }

        public TFSIdentity GetCurrentAuthorizedUserIdentity()
        {
            var authorizedId = this.Connection.SelectedTeamProjectCollection.AuthorizedIdentity;

            var id = this.serverGroupSecurityService.ReadIdentity(SearchFactor.Sid, authorizedId.Descriptor.Identifier, QueryMembership.None);

            return new TFSIdentity(this.Connection, id);
        }

        public TFSIdentity GetUserIdentity(string memberSid)
        {
            Identity memberInfo = this.serverGroupSecurityService.ReadIdentity(SearchFactor.Sid, memberSid, QueryMembership.None);
            if (memberInfo.Type == IdentityType.WindowsUser)
            {
                return new TFSIdentity(Connection, memberInfo);
            }

            throw new TFSUserNotFoundException("User: " + memberSid);
        }

        public TFSIdentityCollection GetUserIdentities()
        {
            this.Connection.CheckConnection();

            // Extract Sid values from Application Groups returned from SecurityService.ListApplicationGroups method
            var appGroupSids = from appGroup in this.serverGroupSecurityService.ListApplicationGroups(Connection.SelectedProject.ServerEntity.ArtifactUri.AbsoluteUri)
                               select appGroup.Sid;

            // Retrieve list of Identities for the Application Groups
            Identity[] groupMembers = this.serverGroupSecurityService.ReadIdentities(SearchFactor.Sid, appGroupSids.ToArray(), QueryMembership.Expanded);

            // Iteration through each Application Group and extract unique User Sids
            List<string> userSids = new List<string>();
            foreach (Identity member in groupMembers)
            {
                if (member.Members != null)
                {
                    foreach (string memberSid in member.Members)
                    {
                        if (!userSids.Contains(memberSid))
                        {
                            userSids.Add(memberSid);
                        }
                    }
                }
            }

            // Retrieve, sort and return list of User Identites
            var usernames = this.serverGroupSecurityService.ReadIdentities(SearchFactor.Sid, userSids.ToArray(), QueryMembership.Expanded).ToList();
            usernames.Sort();

            return TFSIdentityCollection.Create(this.Connection, usernames);
        }
    }
}
